 /*
===========================================================================

  Copyright (c) 2010-2014 Darkstar Dev Teams

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see http://www.gnu.org/licenses/

  This file is part of DarkStar-server source code.

===========================================================================
*/

#include "mob_spell_container.h"
#include "utils/battleutils.h"

CMobSpellContainer::CMobSpellContainer(CMobEntity* PMob)
{
    m_PMob      = PMob;
    m_hasSpells = false;
}

/************************************************************************
*                                                                       *
*  Clear all mob spells from the container                              *
*                                                                       *
************************************************************************/

void CMobSpellContainer::ClearSpells()
{
    m_gaList.clear();
    m_damageList.clear();
    m_buffList.clear();
    m_healList.clear();
    m_naList.clear();
    m_hasSpells = false;
}

void CMobSpellContainer::AddSpell(int16 spellId)
{
    // Get spell
    CSpell* spell = spell::GetSpell(spellId);

    if(spell == NULL)
    {
        ShowDebug("Missing spellID = %d, given to mob. Check spell_list.sql\n", spellId);
        return;
    }

    m_hasSpells = true;

    // Add spell to correct vector
    // Try to add it to ga list first
    uint8 aoe = battleutils::GetSpellAoEType(m_PMob, spell);
    if(aoe > 0 && spell->canTargetEnemy())
    {

        m_gaList.push_back(spellId);

    }
    else if(spell->canTargetEnemy())
    {
        // Add to damage list
        m_damageList.push_back(spellId);

    }
    else if(spell->isNa() || spellId == 143)
    {
        // Na spell and erase
        m_naList.push_back(spellId);

    }
    else if(spell->isHeal())
    {	// Includes Blue mage healing spells, wild carrot etc
        // Add to healing
        m_healList.push_back(spellId);

    }
    else if(spell->isBuff())
    {
        // Buff
        m_buffList.push_back(spellId);

    }
    else
    {
        ShowDebug("Where does this spell go? %d\n", spellId);
    }
}

/************************************************************************
*                                                                       *
*  Does the mob have any spells                                         *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasSpells()
{
    return m_hasSpells;
}

/************************************************************************
*                                                                       *
*  Does the mob have spells that use MP                                 *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasMPSpells()
{

    for (std::vector<int16>::iterator it = m_damageList.begin() ; it != m_damageList.end(); ++it)
    {
        if(spell::GetSpell((*it))->hasMPCost())
        {
            return true;
        }
    }

    for (std::vector<int16>::iterator it = m_buffList.begin() ; it != m_buffList.end(); ++it)
    {
        if(spell::GetSpell((*it))->hasMPCost())
        {
            return true;
        }
    }

    return false;
}

/************************************************************************
*                                                                       *
*  Return a mob spell that will aggro a group                           *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetAggroSpell()
{
    // High chance to return ga spell
    if(HasGaSpells() && rand()%100 <= m_PMob->getMobMod(MOBMOD_GA_CHANCE))
    {
        return GetGaSpell();
    }

    // Else to return damage spell
    return GetDamageSpell();
}

/************************************************************************
*                                                                       *
*  Decide which mob spells to cast                                      *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetSpell()
{
    int16 spellId = -1;
    // Prioritize curing if health low enough
    if(HasHealSpells() && m_PMob->GetHPP() <= m_PMob->getMobMod(MOBMOD_HP_HEAL_CHANCE) && rand()%100 < m_PMob->getMobMod(MOBMOD_HEAL_CHANCE))
    {
        return GetHealSpell();
    }

    // Almost always use na if I can
    if(HasNaSpells() && rand()%100 < m_PMob->getMobMod(MOBMOD_NA_CHANCE))
    {
        // Will return -1 if no proper na spell exists
        spellId = GetNaSpell();
        if(spellId > -1)
        {
            return spellId;
        }
    }

    // Try ga spell
    if(HasGaSpells() && rand()%100 < m_PMob->getMobMod(MOBMOD_GA_CHANCE))
    {
        return GetGaSpell();
    }

    if(HasBuffSpells() && rand()%100 < m_PMob->getMobMod(MOBMOD_BUFF_CHANCE))
    {
        return GetBuffSpell();
    }

    // Try damage spell
    return GetDamageSpell();
}

/************************************************************************
*                                                                       *
*  Return a Ga spell from the mobs list if any                          *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetGaSpell()
{
    if(m_gaList.empty()) return -1;

    return m_gaList[rand()%m_gaList.size()];
}

/************************************************************************
*                                                                       *
*  Return a damaging spell from the mobs list if any                    *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetDamageSpell()
{
    if(m_damageList.empty()) return -1;

    return m_damageList[rand()%m_damageList.size()];
}

/************************************************************************
*                                                                       *
*  Return a buffing spell from the mobs list if any                     *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetBuffSpell()
{
    if(m_buffList.empty()) return -1;

    return m_buffList[rand()%m_buffList.size()];
}

/************************************************************************
*                                                                       *
*  Return a healing spell from the mobs list if any                     *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetHealSpell()
{
    if(m_PMob->m_EcoSystem == SYSTEM_UNDEAD || m_healList.empty()) return -1;

    return m_healList[rand()%m_healList.size()];
}

/************************************************************************
*                                                                       *
*  Return a Na spell from the mobs list if any                          *
*                                                                       *
************************************************************************/

int16 CMobSpellContainer::GetNaSpell()
{
    if(m_naList.empty()) return -1;

    // Paralyna
    if(HasNaSpell(15) && m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_PARALYSIS))
    {
        return 15;
    }

    // Cursna
    if(HasNaSpell(20) && (m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_CURSE_I) || m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_CURSE_II)))
    {
        return 20;
    }

    // Erase
    if(HasNaSpell(143) && m_PMob->StatusEffectContainer->HasStatusEffectByFlag(EFFECTFLAG_ERASABLE))
    {
        return 143;
    }

    // Blindna
    if(HasNaSpell(16) && m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_BLINDNESS))
    {
        return 16;
    }

    // Poisona
    if(HasNaSpell(14) && m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_POISON))
    {
        return 14;
    }

    // Viruna? whatever ignore
    // Silena ignore
    // Stona ignore

    return -1;
}

/************************************************************************
*                                                                       *
*  Does the mobs have any Ga spells                                     *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasGaSpells()
{
    return !m_gaList.empty();
}

/************************************************************************
*                                                                       *
*  Does the mobs have any damaging spells                               *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasDamageSpells()
{
    return !m_damageList.empty();
}

/************************************************************************
*                                                                       *
*  Does the mobs have any buffing spells                                *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasBuffSpells()
{
    return !m_buffList.empty();
}

/************************************************************************
*                                                                       *
*  Does the mobs have any healing spells                                *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasHealSpells()
{
    return !m_healList.empty();
}

/************************************************************************
*                                                                       *
*  Does the mobs have any Na spells                                     *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasNaSpells()
{
    return !m_naList.empty();
}

/************************************************************************
*                                                                       *
*  Does the mobs have a specific Na spell                               *
*                                                                       *
************************************************************************/

bool CMobSpellContainer::HasNaSpell(int16 spellId)
{

    for(std::vector<int16>::iterator iter = m_naList.begin(); iter != m_naList.end(); iter++)
    {
        if(*iter == spellId)
        {
            return true;
        }
    }
    return false;
}
